#!/usr/bin/perl

#
#    _                           _                       _
#   | |_ ___ _ __ ___   __ _  __| |_ __ ___        _ __ | |
#   | __/ __| '_ ` _ \ / _` |/ _` | '_ ` _ \      | '_ \| |
#   | |_\__ \ | | | | | (_| | (_| | | | | | |  _  | |_) | |
#    \__|___/_| |_| |_|\__,_|\__,_|_| |_| |_| (_) | .__/|_|
#                                                 |_|
#              Visit at: http://www.tsmadm.pl/
#

# tsmadm.pl is an open source multi platform really task oriented IBM Tivoli Storage Manager command line interface
#
# Designed by _flex and Marcell
# Written by _flex from FleXoft and Marcell.
#   (flex@tsmadm.pl) (marcell@tsmadm.pl)
#
# v1.00, 2011.06.01. Budapest, FleXoft
#	Rls:	first release
#
# Requirements:
# -------------
#
#      Perl:
#
# Documentation:
# --------------
#
#      Tested on:
#        HPUX (B.11.11)
#        MS Windows (Version 5.1 (Build 2600.xpsp_sp2_gdr.050301-1519 : Service Pack 2))
#        Sun Solaris 9 ()
#        Debian Linux ()
#
#      with TSM servers:
#        Server Version 5, Release 5, Level 5.2
#
# TODO:
# -----
#
# =========================================================================
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
#
# *************************************************************************

use strict;
use warnings;

require 5.008_000;    # perl 5.10.0... compatible

# store the starting time
my $starttime = time;

# and get the starting dir
our $Dirname = dirname($0);    #
our @History;
our $HistoryPointer = 0;

# load perl modules
use Time::Local;
use Getopt::Long;
use File::Path;
use File::Spec;
use File::Basename;
use Pod::Usage;
use utf8;


# load perl subroutines
require "$Dirname/subs/tsmadm_subroutines.pl";
require "$Dirname/subs/dsmadmc_subroutines.pl";
require "$Dirname/subs/marcell_subroutines.pl";
require "$Dirname/subs/perec_subroutines.pl";
require "$Dirname/subs/wizard_subroutines.pl";

require "$Dirname/subs/archive_subroutines.pl";

# prepare options for Getopt
my $helpFlag;
my $manualFlag;
my $verboseFlag;
my $quietFlag;
my $configfileOption;
my $commandOption;
my $serverOption;
my $languageOption;
my $defaultColorOption;
my $nocolorFlag;
my $promptOptions;
my $Server;
my $disableGrep;
my $debugFlag;
my $consoleFlag;
my $wizardFlag;

if (
     !GetOptions(
                  "help"           => \$helpFlag,
                  "manual"         => \$manualFlag,
                  "debug"          => \$debugFlag,
                  "quiet"          => \$quietFlag,
                  "nocolor"        => \$nocolorFlag,
                  "console"        => \$consoleFlag,
                  "wizard"         => \$wizardFlag,
                  "server=s"       => \$serverOption,
                  "configfile=s"   => \$configfileOption,
                  "command=s"      => \$commandOption,
                  "language=s"     => \$languageOption,
                  "defaultcolor=s" => \$defaultColorOption,
                  "prompt=s"       => \$promptOptions,
                )
   )
{
    exit 1;    # Wrong parameter usage!
}

# Help & Manual handling
pod2usage( -verbose => 1, -message => "tsmadm.pl" ) if ( defined($helpFlag) );
pod2usage( -verbose => 2, -message => "tsmadm.pl" ) if ( defined($manualFlag) );

# Global variables (Each starts with capital!)
our $tsmadmplVersion;    # version info

our %Settings;           # Global settings hash

our %Messages;           # Global message hash

our $LastErrorcode;      # Last dsmadmc error code
our $LastErrorMessage;   # Last dsmadmc error message

our $ExcludeList = '^\s*$';    # dsmadmc exclude list
$ExcludeList .= '|^IBM Tivoli Storage Manager.*$';                           #
$ExcludeList .= '|^Tivoli Storage Manager.*$';                               #
$ExcludeList .= '|^Command Line Administrative Interface.*$';                #
$ExcludeList .= '|^\(c\) Copyright by IBM Corporation and other\(s\).*$';    #
$ExcludeList .= '|^\(C\) Copyright IBM Corporation.*$';                      #
$ExcludeList .= '|^Session established with server.*$';                      #
$ExcludeList .= '|^\s\sServer.*$';                                           #

#
$ExcludeList .= '|^ANS0102W.*$';                                             # ANS0102W QUERY PROCESS: No active processes found.

#
$ExcludeList .= '|^ANR0944E.*$';                                             # ANR0944E QUERY PROCESS: No active processes found.

#
$ExcludeList .= '|^ANR1462I.*$';    # ANR1462I RUN: Command script SCRIPTNAME completed successfully.

#
$ExcludeList .= '|^ANR1687I.*$';    # ANR1687I Output for command 'COMMAND' issued against server SERVERNAME follows:
$ExcludeList .= '|^ANR1688I.*$';    # ANR1688I Output for command 'COMMAND' issued against server SERVERNAME completed.
$ExcludeList .= '|^ANR1694I.*$';    # ANR1694I Server SERVERNAME processed command 'COMMAND' and complete d successfully.
$ExcludeList .= '|^ANR1695W.*$';    # ANR1695W Server SERVERNAME processed command 'COMMAND' but complet ed with warnings.
$ExcludeList .=
  '|^ANR1697I.*$';    # ANR1697I Command 'COMMAND' processed by ## server(s):  ## successful, # with warnings, and # with errors.
$ExcludeList .= '|^ANR1699I.*$';    # ANR1699I Resolved SITE to ## server(s) - issuing command COMMAND against server(s).

#
$ExcludeList .= '|^ANR2034E.*$';    # ANR2034E QUERY EVENT: No match found using this criteria.
$ExcludeList .= '|^ANR2624E.*$';    # ANR2624E QUERY EVENT: No matching nodes registered.

#
$ExcludeList .= '|^ANS8000I.*$';
$ExcludeList .= '|^ANS8001I.*$';    # ANS8001I Return code ##.
$ExcludeList .= '|^ANR8334I.*$';    # ANR8334I         # matches found.
$ExcludeList .= '|^ANR2662I.*$'
  ;    # ANR2662I (*) "Query schedule format=standard" displays an asterisk in the day of week column for enhanced schedules.

our $TmpExcludeList = "";    # you can add more with 'exclude' command

our $OS_win = ( $^O eq "MSWin32" ) ? 1 : 0;    # Is it MS Windows?

our %ParameterRegExps = (                      # This hash helps to get the command parameters
    HIGHLIGHT => '-*(highlight)=(.+)',                   #
    NOHISTORY => '-*(nohistory)',                        #
    REPEAT    => '-*(repeat)=(\d+x\d+|\d+)',             #
    NOCOLOR   => '-*(nocolor)',                          #
    HTML      => '-*(html)',                             #
    MAIL      => '-*(mail)=(\w+@[\w+\.\w+]+)',           #
    HELP      => '-*(help)',                             #
    HISTORY   => '-*(archive|archiv|archi|arch|arc)',    #

    INVGREP => '\|\s*(invgrep)\s+(.+)',                  #
    GREP    => '\|\s*(grep)\s+(\w+)',                    #
    MORE    => '\|\s*(more)',                            #

    OUTPUT => '(\>)\s*(.+)',                             #

                        );

our %ParameterRegExpValues = ();                         # This hash stores the values

our %Commands;                                           #

our %Aliases;                                            #

our $LastCommandType;                                    #

our @LastResult;                                         #

our %TSMSeverStatus;                                     #

our $CurrentPrompt;                                      #

our $CommandMode = "BATCH";                              # INTERACTIVE, BATCH

#our %GlobalHighlighter = (
#  RED  => '[a-zA-Z]\d\d\d\d\d', ## Volume name
#  BLUE => 'TSM',                ## Test
#);

our %GlobalHighlighter = (
    'B\d\d\d\d\d'                                    => 'BOLD GREEN',
    'A\d\d\d\d\d[a-zA-Z][a-zA-Z]'                    => 'BOLD GREEN',
    '[a-zA-Z][a-zA-Z][a-zA-Z]\d\d\d[a-zA-Z][a-zA-Z]' => 'BOLD GREEN',
    'MediaW'                                         => 'RED',
    'ANR\d\d\d\dE'                                   => 'BOLD RED',
    'ANR\d\d\d\dW'                                   => 'BOLD YELLOW',

    #    'dsmadmc'            => 'BLUE',
    #    '\d\d\d'             => 'WHITE',
    #    'OR{'                => 'MAGENTA',
    #    'QGXV'                => 'CYAN',
    #    'ba'                   => 'WHITE',
    #    'baclient'            => "GREEN",
    #   'client'                 => 'BLACK',

                         );

##########################################################################################
# main()
##########################################################################################

# get the version info first
open my $MYSELF, "<$0" or die;
while (<$MYSELF>) {
    if (/^# v(\d+\.\d{2}),/) {
        $tsmadmplVersion = $1;
        last;
    }
}
close $MYSELF or die;


$Settings{HOMEDIRECTORY} = "";

# OS
if ($OS_win) {

    # MS Windows environments
    require Win32;
    require Win32::Console;
    require Win32::Console::ANSI;

    $Settings{HOMEDIRECTORY} = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};

}
else {

    # UNIX like environments
    use Term::ReadKey;
    use Term::ANSIColor;
    $Settings{HOMEDIRECTORY} = $ENV{HOME};

}

# load config file DON'T MOVE THIS SECTION!
if ( !defined($configfileOption) ) {

    # default config file
    $configfileOption = "$Settings{HOMEDIRECTORY}/.tsmadm/tsmadm.conf";
}


$Settings{CONFIGFILE} = $configfileOption;


# Wizard
if ( defined($wizardFlag) ) {
    &wizard;
    exit;
}

# check Configfile 
if (! -r $Settings{CONFIGFILE} ) {
    print "Config file ($Settings{CONFIGFILE}) can not be found, or not readable! Starting Configuration Wizard...\n";
    system("$0 -wizard");
    exit 1;
}

&checkPassword($configfileOption);

%Settings = &loadFileToHash($configfileOption);

$Settings{CONFIGFILE} = $configfileOption;

# put it to the right place and use from here


$Settings{HISTORYFILE}      = "$Settings{HOMEDIRECTORY}/.tsmadm/command_history";
$Settings{ARCHIVEDIRECTORY} = "$Dirname/archives";

# load language file
if ( defined($languageOption) ) {
    $Settings{LANGUAGE} = $languageOption;
}
elsif ( !defined( $Settings{LANGUAGE} ) ) {
    $Settings{LANGUAGE} = "en_US";
}

%Messages = &loadFileToHash( "$Dirname/languages/" . $Settings{LANGUAGE} . ".txt" );

&updateTerminalSettings();

&checkDefaults();

if ( defined($defaultColorOption) && defined($nocolorFlag) ) {
    pod2usage(
               {
                -verbose => 1,
                -exitval => 1,
                -message => "--defaultcolor and --nocolor are mutually exclusive.\n"
               }
             );
}

# default color
if (
     defined($defaultColorOption)
     && (    uc($defaultColorOption) eq "RED"
          || uc($defaultColorOption) eq "BLUE"
          || uc($defaultColorOption) eq "WHITE"
          || uc($defaultColorOption) eq "BLACK"
          || uc($defaultColorOption) eq "YELLOW"
          || uc($defaultColorOption) eq "MAGENTA"
          || uc($defaultColorOption) eq "CYAN"
          || uc($defaultColorOption) eq "GREEN" )
   )
{

    $Settings{DEFAULTCOLOR} = uc($defaultColorOption);
}
elsif ( !defined( $Settings{DEFAULTCOLOR} ) ) {

    # $Settings{DEFAULTCOLOR} = "WHITE";
}

# nocolor
if ( defined($nocolorFlag) ) {
    $Settings{NOCOLOR} = 1;
}
elsif ( !defined( $Settings{NOCOLOR} ) ) {
    $Settings{NOCOLOR} = 0;
}

# prompt
if ( defined($promptOptions) ) {
    $Settings{PROMPT} = $promptOptions;
}
elsif ( !defined( $Settings{PROMPT} ) ) {
    $Settings{PROMPT} = "TSMADM: ";
}

# Server
if ( defined($serverOption) ) {
    $Settings{SERVER} = uc("$serverOption");
}
elsif ( !defined( $Settings{SERVER} ) ) {
    $Settings{SERVER} = $Settings{DEFAULTSERVER};
}


# Disable Grep
if ( defined($disableGrep) ) {
    $Settings{DISABLEGREP} = 1;
}
elsif ( !defined( $Settings{DISABLEGREP} ) ) {
    $Settings{DISABLEGREP} = 0;
}

$Settings{OS} = $^O;

if ( defined($quietFlag) && defined($debugFlag) ) {
    pod2usage(
               {
                -verbose => 1,
                -exitval => 1,
                -message => "--quiet and --debug are mutually exclusive.\n"
               }
             );
}

#quiet flag
if ( defined($quietFlag) ) {
    $Settings{QUIET} = 1;
    $Settings{DEBUG} = 0;
}
else {
    $Settings{QUIET} = 0;
}

if ( defined($debugFlag) ) {
    $Settings{DEBUG} = 1;
}
else {
    $Settings{DEBUG} = 0;
}

if ( defined($consoleFlag) ) {
    print &colorString( "Starting Console Highlighter...\n", "BOLD RED" );
    &consoleHighlighter;
    exit 0;
}

# Welcome message
print colorString( "", $Settings{DEFAULTCOLOR} );
&msg( '0000C', &colorString( "tsmadm.pl v" . $tsmadmplVersion, 'BOLD WHITE' ) );

# load plugins
&reLoadPlugins();

# set server
&setServer( $Settings{SERVER} )
  if ( defined( $Settings{SERVER} ) && $Settings{SERVER} ne "" );

# update prompt
&updatePrompt();

# signal
$SIG{INT} = \&sigInt;

# if command parameter was used then do it
if ( defined( $commandOption ) && &commandSplitterParserExecuter($commandOption) == 1 ) {
    ;
}
# if AUTOEXEC parameter was used in the config file then do it
elsif ( defined( $Settings{AUTOEXEC} ) && &commandSplitterParserExecuter( $Settings{AUTOEXEC} ) == 1 ) {
    ;
}
else {

    $CommandMode = "INTERACTIVE";

    # main loop
    INFINITELOOP: while (1) {

        print $CurrentPrompt;
        my $command = &readCommand;

        next if ( !defined($command) );

        chomp($command);

        # !end!
        #last if ( $command =~ m/^\s*(quit|exit|bye|logout|end)/i );

        last if ( &commandSplitterParserExecuter($command) == 1 );

    }    # END of infinite loop
}

# End summary
&msg( '9900I', &msgSpentTime( time - $starttime ) );
&msg( '9901I', 'http://tsmadm.com/' );
&msg('9999I');

__END__

=head1 NAME

tsmadm.pl - Advanced Tivoli Storage Manager Administration Client

=head1 SYNOPSIS

B<tsmadm.pl --help>

B<tsmadm.pl --manual>

B<tsmadm.pl --wizard>

B<tsmadm.pl --console> [ B<--server> I<serverName> ]

B<tsmadm.pl> [ B<--debug> | B<--quiet> ] [ B<--nocolor> | B<--defaultcolor> I<defaultColor> ] [ B<--server> I<serverName> ] [ B<--configfile> I<configFile> ]
[ B<--command> I<command> ] [ B<--language> I<language> ] [ B<--prompt> I<prompt> ]

=head1 DESCRIPTION

B<tsmadm.pl> is a command line wrapper for dsmadmc, the administration client to IBM's Tivoli Storage Management server. It helps you with an extensive and extensible command set, highlighting, better output formatting, and high customizability.

=head1 OPTIONS

=over 4

=item B<--help>

Help about the command line arguments and options. After this tsmadm.pl will exits

=item B<--manual>

A complete manual page about the tsmadm. After this the program will exits

=item B<--debug>

Debug mode

=item B<--wizard>

Starts configuration wizard

=item B<--console>

Console mode, like in dsmadmc + color highlighting

=item B<--quiet>

The silent mode switch.

=item B<--nocolor>

Use this option if your terminal doesnot understand the coloring escape sequences. (eg. you see something like this: \e[xx.xx)

=item B<--server> I<server>

Connect to the specifed server, after start. (A szervernek szerepelnie kell a config fájlban)

=item B<--configfile> I<configFile>

Use alternate configfile (the default is <HOMEDIRECTORY>/.tsmadm/tsmadm.conf)

=item B<--command> I<commands>

Like autoexec.bat :-) try this: --command 'q sess; q pr; quit'

=item B<--defaultcolor> I<defaultColor>

Possible colors are: WHITE, BLACK, RED, BLUE, MAGENTA, YELLOW, GREEN, CYAN

=item B<--language> I<language>

You can use your own language file from I<languages/> directory.

=item B<--prompt> I<value>

The value of this parameter is used as the prompt string.

=back

=head1 FILES

=over 4

=item B<~/.tsmadm/>

This folder contains your personal I<tsmadm.pl> command-line history

=item B<tsmadm.pl>

The perl program

=back

=head1 DIAGNOSTICS

Please see I<languages/*.txt> file for more and possible error messages. The languages directory can be found in your installation directory, by default: /opt/tsmadm/

=head1 REQUIRES

Perl 5.008, Term::ReadKey, Getopt::Long, Pod::Usage, List::Util, Term::ANSIColor, Win32::Console::ANSI (only on windows), File::Path, File:Basename

=head1 SEE ALSO

TSMADM Installation Guide, TSMADM Administration and User's Guide, TSMADM Plug-in Developer's Guide, L<Tivoli Storage Manager|http://www-01.ibm.com/software/tivoli/products/storage-mgr/>, L<IBM|http://www.ibm.com>

=head1 COPYRIGHT

L<GNU General Public License, Version 2|http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>

=head1 AUTHORS

The Fantastic Three

=cut

